#include "preHeader.h"
#include "CenterSession.h"
#include "CenterSessionHandler.h"
#include "SocialServerSession.h"
#include "GateServerMgr.h"
#include "MapServerMgr.h"
#include "ServerMaster.h"
#include "GameServer.h"
#include "network/ConnectionManager.h"
#include "WordFilter/WordFilter.h"

CenterSession::CenterSession()
: RPCSession(SCT_RPC_INVOKE_RESP)
, m_serverId(0)
{
}

CenterSession::~CenterSession()
{
	for (auto pck : m_toSendPckList) {
		delete pck;
	}
}

void CenterSession::CheckConnection()
{
	const auto& connPrePtr = GetConnection();
	if (connPrePtr && connPrePtr->IsActive()) {
		return;
	}
	if (!IsStatus(Idle)) {
		return;
	}

	auto& cfg = IServerMaster::GetInstance().GetConfig();
	auto connPtr = sConnectionManager.NewConnection(*this);
	connPtr->AsyncConnect(
		cfg.GetString("CENTER_SERVER", "HOST", "127.0.0.1"),
		cfg.GetString("CENTER_SERVER", "PORT", "9800"));

	sSessionManager.AddSession(this);
}

void CenterSession::SendPacket(const INetPacket& pck)
{
	if (IsReady()) {
		PushSendPacket(pck);
	} else {
		m_toSendPckList.push_back(pck.Clone());
	}
}

int CenterSession::HandlePacket(INetPacket *pck)
{
	return sCenterSessionHandler.HandlePacket(this, *pck);
}

void CenterSession::OnConnected()
{
	NetPacket req(CCT_REGISTER);
	req << IServerMaster::GetInstance().GetConfig().
		GetString("CENTER_SERVER", "NAME", "main");
	PushSendPacket(req);
	RPCSession::OnConnected();
}

void CenterSession::OnShutdownSession()
{
	WLOG("Close CenterSession [serverId:%u].", m_serverId);
	Session::OnShutdownSession();
}

void CenterSession::DeleteObject()
{
	ClearRecvPacket();
	ClearShutdownFlag();
	SetStatus(Idle);
}

int CenterSessionHandler::HandleRegisterResp(CenterSession *pSession, INetPacket &pck)
{
	int32 errCode;
	std::string_view errMsg;
	pck >> errCode >> errMsg;
	if (errCode != 0) {
		WLOG("Center Session Resp message[%u] %.*s.\n",
			pck.GetOpcode(), int(errMsg.size()), errMsg.data());
		return SessionHandleKill;
	}

	pck >> pSession->m_serverId;
	sSocialServerSession.PushServerId(pSession->m_serverId);
	sGateServerMgr.BroadcastServerId2AllGateServer(pSession->m_serverId);
	sMapServerMgr.BroadcastServerId2AllMapServer(pSession->m_serverId);

	pSession->OnRPCSessionReady();

	for (auto pck : pSession->m_toSendPckList) {
		pSession->PushSendPacket(*pck);
		delete pck;
	}
	pSession->m_toSendPckList.clear();

	NLOG("Register to CenterServer Success As [serverId:%u].",
		pSession->m_serverId);

	return SessionHandleSuccess;
}

int CenterSessionHandler::HandlePushWordFilter(CenterSession *pSession, INetPacket &pck)
{
	enum {Add, Remove, Replace};
	auto PushWordFilter = [pckPtr = std::shared_ptr<INetPacket>(&pck)]() {
		int8 type;
		std::vector<std::string_view> words;
		(*pckPtr) >> type;
		while (!pckPtr->IsReadableEmpty()) {
			words.push_back(pckPtr->Read<std::string_view>());
		}
		switch (type) {
		case Add: sWordFilter.AddWords(words); break;
		case Remove: sWordFilter.RemoveWords(words); break;
		case Replace: sWordFilter.ReplaceWords(words); break;
		}
	};
	sDeferAsyncTaskMgr.AddTask(CreateAsyncTask(PushWordFilter, [](AsyncTaskOwner*) {
		sGameServer.CreateTimerX(std::bind(
			&WordFilter::FreeObsoleteInsts, &sWordFilter, GET_UNIX_TIME), 60, 1);
	}), &sGameServer, __LINE__);
	return SessionHandleCapture;
}
